package beans;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Properties;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;

import model.ACLMessage;
import model.AgentInfo;
import model.Host;
import util.HashMapWrapper;
import webservice.NodeCommunicationWS;
import agents.Agent;
import beans.interfaces.AgentDataLocal;

/**
 * Session Bean implementation class ConnectionManager
 */
@Singleton
@Startup
@LocalBean
public class ConnectionManager implements ConnectionManagerLocal {

    /**
     * Default constructor. 
     */
	@EJB
	private AgentDataLocal agentData;
	
	@EJB
	private NodeCommunicationWS localNode;

	private NodeCommunicationWS service;

	private String thisServerAddress;

	private String defaultHostAddress;

	private boolean first;

	private String httpHeader="";//"http://";

	private String wsdlLocation="";//":8080/chatAgentsEJB/NodeCommunication/NodeCommunicationBean?wsdl";

	private QName serviceName = new QName("http://1337.webservice",
			"NodeCommunication");

	private Host localHost;
	
    public ConnectionManager() {
        // TODO Auto-generated constructor stub
    	// Ucitavanje adrese iz konfiguracionog fajla
    			Properties prop = new Properties();
    			InputStream input = null;

    			try {

    				input = new FileInputStream(
    						"../standalone/deployments/chatAgentsEAR.ear/config.properties");

    				// load a properties file
    				prop.load(input);

    				// get the property value and print it out
    				thisServerAddress = prop.getProperty("ServerAddress");
    				defaultHostAddress = prop.getProperty("defaultHostAddress");
    				String firstt = prop.getProperty("isBootingFirst");
    				httpHeader=prop.getProperty("httpHeader");
    				wsdlLocation = prop.getProperty("wsdlLocation");
    				if (firstt.toLowerCase().equals("true")) {
    					first = true;
    				} else {
    					first = false;
    				}
    				localHost = new Host(thisServerAddress, null);

    			} catch (IOException ex) {
    				ex.printStackTrace();
    			} finally {
    				if (input != null) {
    					try {
    						input.close();
    					} catch (IOException e) {
    						e.printStackTrace();
    					}
    				}
    			}
    }
    
    @PostConstruct
    private void init() {
    	agentData.setLocalhost(localHost);
    	agentData.addHost(localHost);
    	registerWithOtherNodes();
    }

    @Override
    public void sendToOtherServer(ACLMessage aclMessage) {
    	if(aclMessage!=null) {
    		//ako je poruka za sve, salji svim cvorovima
			if(aclMessage.getReciever()==null) {
				for(Host h : agentData.getHosts()) {
					if(!h.equals(localHost)){
						
						try {
							Service temp = Service
									.create(new URL(httpHeader+h.getAddress()+wsdlLocation), serviceName);
							service = temp.getPort(NodeCommunicationWS.class);

							service.publish(aclMessage);

						} catch (MalformedURLException e) {
							e.printStackTrace();
						}
						
					}
				}
			} else if(!aclMessage.getReciever().getLocalHost().equals(localHost)) {
				try {
					Service temp = Service
							.create(new URL(httpHeader+aclMessage.getReciever().getLocalHost().getAddress()+wsdlLocation), serviceName);
					service = temp.getPort(NodeCommunicationWS.class);
					
					service.publish(aclMessage);

				} catch (MalformedURLException e) {
					e.printStackTrace();
				}
			}
		}
    }
    
    @Override
    public Host getLocalhost() {
    	return localHost;
    }
    
    @Override
    public void registerWithOtherNodes() {
    	if (!first) {
			try {
				Service temp = Service.create(new URL(httpHeader
						+ defaultHostAddress + wsdlLocation), serviceName);
				service = temp.getPort(NodeCommunicationWS.class);
				List<Host> hostsRemote = service.register(localHost);
				if (hostsRemote != null) {
					agentData.addHosts(hostsRemote);
				}
				//service.updateAgentList(new HashMapWrapper(agentData.getAgents()));
			} catch (MalformedURLException e) {
				e.printStackTrace();
			}
		}
    }
    
    @Override
    public void syncAgentsWithOtherNodes() {
    	if(service!=null) {
    		service.updateAgentList(new HashMapWrapper(agentData.getAgents()));
    	}
    }
    
    @Override
    public Agent findAgentOnRemoteNode(String key) {
    	for(Host h : agentData.getHosts()) {
			if(!h.equals(agentData.getLocalHost())){
				
				try {
					Service temp = Service
							.create(new URL(httpHeader+h.getAddress()+wsdlLocation), serviceName);
					service = temp.getPort(NodeCommunicationWS.class);
					
					
					Agent a = service.getAgent(key);
					
					if(a!=null) {
						return a;
					}

				} catch (MalformedURLException e) {
					e.printStackTrace();
				}
				
			}
		}
    	return null;
    }
    
    @Override
    public AgentInfo findAnyMasterAgentInfoOnOtherNode() {
    	System.out.println("trazim mastera na drugom serveru.");
    	for(Host h : agentData.getHosts()) {
			if(!h.equals(agentData.getLocalHost())){
				try {
					System.out.println("host:"+h);
					Service temp = Service
							.create(new URL(httpHeader+h.getAddress()+wsdlLocation), serviceName);
					service = temp.getPort(NodeCommunicationWS.class);
					
					
					AgentInfo ai = service.getAnyMasterAgentInfo();
					
					if(ai!=null) {
						System.out.println("nasao agentinfo:"+ai);
						return ai;
					}

				} catch (MalformedURLException e) {
					e.printStackTrace();
				}
				
			}
		}
    	System.out.println("nisam nasao ni jednog agenta");
    	return null;
    }
    
	@PreDestroy
	private void notifyShutdown() {
		Service temp;
		if(agentData.getHosts().size()>1) {
			try {
				temp = Service.create(new URL(httpHeader + defaultHostAddress
						+ wsdlLocation), serviceName);
				service = temp.getPort(NodeCommunicationWS.class);
				service.unregister(localHost);
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public String getHttpHeader() {
		return httpHeader;
	}

	public String getWsdlLocation() {
		return wsdlLocation;
	}

	public QName getServiceName() {
		return serviceName;
	}

	public Host getLocalHost() {
		return localHost;
	}
}
